package com.bit.net;

import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;

import static com.bit.net.Messages.*;

/**
 * 请求报文解码
 *
 * @since 2018/10/10
 */
@Slf4j
public class RequestDecoder extends ByteToMessageDecoder {

    private EachModulModelMessages modelMessages;

    public RequestDecoder(EachModulModelMessages modelMessages) {
        this.modelMessages = modelMessages;
    }

    @Override
    public void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        if (byteBuf.readableBytes() < MIN_PKG_SIZE) {
            return;
        }

        if (log.isDebugEnabled()) {
            log.debug("[GameRequestDecoder.decode] received package head:{}", ByteBufUtil.hexDump(byteBuf));
        }

        int readerIndex = byteBuf.readerIndex();
        log.debug("[GameRequestDecoder.decode] byteBuf reader index:{}", readerIndex);

        // 检查魔数
        byte[] magicNumber = new byte[MAGIC_NUMBER_SIZE];
        byteBuf.getBytes(readerIndex, magicNumber, 0, magicNumber.length);

        if (!Arrays.equals(MAGIC_NUMBER, magicNumber)) {
            log.warn("[GameRequestDecoder.decode] get an unsupported magic number");
            return;
        }

        // 检查可读字节数
        int packageSize = byteBuf.getUnsignedShort(readerIndex + PKG_SIZE_INDEX);
        if (byteBuf.readableBytes() < packageSize) {
            return;
        }

        // 检查版本
        short version = byteBuf.getUnsignedByte(readerIndex + VERSION_INDEX);
        if (version != DEFAULT_VERSION) {
            log.warn("[GameRequestDecoder.decode] get an unsupported version number:{}", version);
            return;
        }

        // 报文头
        byte[] pkgHeader = new byte[PKG_HEAD_SIZE];
        byteBuf.readBytes(pkgHeader);

        if (log.isDebugEnabled()) {
            log.debug("[GameRequestDecoder.decode] received package head:{}", ByteBufUtil.hexDump(pkgHeader));
        }

        // 请求类型码
        Class<? extends Message> targetClass = modelMessages.getTargetClass(requestCode(pkgHeader));

        if (targetClass == null) {
            log.warn("[GameRequestDecoder.decode] get an unsupported request code:{}", requestCode(pkgHeader));
            return;
        }

        // 报文体
        byte[] pkgBody = new byte[packageSize - PKG_HEAD_SIZE];
        byteBuf.readBytes(pkgBody);

        if (log.isDebugEnabled()) {
            log.debug("[GameRequestDecoder.decode] received package, head:{}", ByteBufUtil.hexDump(pkgHeader));
        }

        // 报文体转字符串
        String bodyContent = new String(pkgBody, CharsetUtil.UTF_8);

        if (log.isDebugEnabled()) {
            log.debug("[GameRequestDecoder.decode] received package, body:{}", bodyContent);
        }

        // 请求
        Message gameRequest = JSON.parseObject(bodyContent, targetClass);
        out.add(gameRequest);
    }

    /**
     * 获取请求报文的类型码
     *
     * @param request 请求报文信息
     * @return 判断结果
     */
    protected int requestCode(byte[] request) {
        return (int) request[CMD_INDEX];
    }

}
